/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package controllers;

import concursos.concurso.Concurso;
import controllers.exceptions.NonexistentEntityException;
import controllers.exceptions.PreexistingEntityException;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import concursos.concurso.Recurso;
import java.util.HashSet;
import java.util.Set;
import concursos.concurso.Inscricao;
import concursos.concurso.FatoRelevante;
import concursos.concurso.Arquivo;
import concursos.prova.Prova;

/**
 *
 * @author lucena
 */
public class ConcursoJpaController {

    public ConcursoJpaController() {
        emf = Persistence.createEntityManagerFactory("concursosPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Concurso concurso) throws PreexistingEntityException, Exception {
        if (concurso.getRecursos() == null) {
            concurso.setRecursos(new HashSet<Recurso>());
        }
        if (concurso.getInscricoes() == null) {
            concurso.setInscricoes(new HashSet<Inscricao>());
        }
        if (concurso.getFatosRelevantes() == null) {
            concurso.setFatosRelevantes(new HashSet<FatoRelevante>());
        }
        if (concurso.getArquivos() == null) {
            concurso.setArquivos(new HashSet<Arquivo>());
        }
        if (concurso.getProvas() == null) {
            concurso.setProvas(new HashSet<Prova>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Set<Recurso> attachedRecursos = new HashSet<Recurso>();
            for (Recurso recursosRecursoToAttach : concurso.getRecursos()) {
                recursosRecursoToAttach = em.getReference(recursosRecursoToAttach.getClass(), recursosRecursoToAttach.getId());
                attachedRecursos.add(recursosRecursoToAttach);
            }
            concurso.setRecursos(attachedRecursos);
            Set<Inscricao> attachedInscricoes = new HashSet<Inscricao>();
            for (Inscricao inscricoesInscricaoToAttach : concurso.getInscricoes()) {
                inscricoesInscricaoToAttach = em.getReference(inscricoesInscricaoToAttach.getClass(), inscricoesInscricaoToAttach.getId());
                attachedInscricoes.add(inscricoesInscricaoToAttach);
            }
            concurso.setInscricoes(attachedInscricoes);
            Set<FatoRelevante> attachedFatosRelevantes = new HashSet<FatoRelevante>();
            for (FatoRelevante fatosRelevantesFatoRelevanteToAttach : concurso.getFatosRelevantes()) {
                fatosRelevantesFatoRelevanteToAttach = em.getReference(fatosRelevantesFatoRelevanteToAttach.getClass(), fatosRelevantesFatoRelevanteToAttach.getId());
                attachedFatosRelevantes.add(fatosRelevantesFatoRelevanteToAttach);
            }
            concurso.setFatosRelevantes(attachedFatosRelevantes);
            Set<Arquivo> attachedArquivos = new HashSet<Arquivo>();
            for (Arquivo arquivosArquivoToAttach : concurso.getArquivos()) {
                arquivosArquivoToAttach = em.getReference(arquivosArquivoToAttach.getClass(), arquivosArquivoToAttach.getId());
                attachedArquivos.add(arquivosArquivoToAttach);
            }
            concurso.setArquivos(attachedArquivos);
            Set<Prova> attachedProvas = new HashSet<Prova>();
            for (Prova provasProvaToAttach : concurso.getProvas()) {
                provasProvaToAttach = em.getReference(provasProvaToAttach.getClass(), provasProvaToAttach.getId());
                attachedProvas.add(provasProvaToAttach);
            }
            concurso.setProvas(attachedProvas);
            em.persist(concurso);
            for (Recurso recursosRecurso : concurso.getRecursos()) {
                Concurso oldConcursoOfRecursosRecurso = recursosRecurso.getConcurso();
                recursosRecurso.setConcurso(concurso);
                recursosRecurso = em.merge(recursosRecurso);
                if (oldConcursoOfRecursosRecurso != null) {
                    oldConcursoOfRecursosRecurso.getRecursos().remove(recursosRecurso);
                    oldConcursoOfRecursosRecurso = em.merge(oldConcursoOfRecursosRecurso);
                }
            }
            for (Inscricao inscricoesInscricao : concurso.getInscricoes()) {
                Concurso oldConcursoOfInscricoesInscricao = inscricoesInscricao.getConcurso();
                inscricoesInscricao.setConcurso(concurso);
                inscricoesInscricao = em.merge(inscricoesInscricao);
                if (oldConcursoOfInscricoesInscricao != null) {
                    oldConcursoOfInscricoesInscricao.getInscricoes().remove(inscricoesInscricao);
                    oldConcursoOfInscricoesInscricao = em.merge(oldConcursoOfInscricoesInscricao);
                }
            }
            for (FatoRelevante fatosRelevantesFatoRelevante : concurso.getFatosRelevantes()) {
                Concurso oldConcursoOfFatosRelevantesFatoRelevante = fatosRelevantesFatoRelevante.getConcurso();
                fatosRelevantesFatoRelevante.setConcurso(concurso);
                fatosRelevantesFatoRelevante = em.merge(fatosRelevantesFatoRelevante);
                if (oldConcursoOfFatosRelevantesFatoRelevante != null) {
                    oldConcursoOfFatosRelevantesFatoRelevante.getFatosRelevantes().remove(fatosRelevantesFatoRelevante);
                    oldConcursoOfFatosRelevantesFatoRelevante = em.merge(oldConcursoOfFatosRelevantesFatoRelevante);
                }
            }
            for (Arquivo arquivosArquivo : concurso.getArquivos()) {
                Concurso oldConcursoOfArquivosArquivo = arquivosArquivo.getConcurso();
                arquivosArquivo.setConcurso(concurso);
                arquivosArquivo = em.merge(arquivosArquivo);
                if (oldConcursoOfArquivosArquivo != null) {
                    oldConcursoOfArquivosArquivo.getArquivos().remove(arquivosArquivo);
                    oldConcursoOfArquivosArquivo = em.merge(oldConcursoOfArquivosArquivo);
                }
            }
            for (Prova provasProva : concurso.getProvas()) {
                Concurso oldConcursoOfProvasProva = provasProva.getConcurso();
                provasProva.setConcurso(concurso);
                provasProva = em.merge(provasProva);
                if (oldConcursoOfProvasProva != null) {
                    oldConcursoOfProvasProva.getProvas().remove(provasProva);
                    oldConcursoOfProvasProva = em.merge(oldConcursoOfProvasProva);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findConcurso(concurso.getId()) != null) {
                throw new PreexistingEntityException("Concurso " + concurso + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Concurso concurso) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Concurso persistentConcurso = em.find(Concurso.class, concurso.getId());
            Set<Recurso> recursosOld = persistentConcurso.getRecursos();
            Set<Recurso> recursosNew = concurso.getRecursos();
            Set<Inscricao> inscricoesOld = persistentConcurso.getInscricoes();
            Set<Inscricao> inscricoesNew = concurso.getInscricoes();
            Set<FatoRelevante> fatosRelevantesOld = persistentConcurso.getFatosRelevantes();
            Set<FatoRelevante> fatosRelevantesNew = concurso.getFatosRelevantes();
            Set<Arquivo> arquivosOld = persistentConcurso.getArquivos();
            Set<Arquivo> arquivosNew = concurso.getArquivos();
            Set<Prova> provasOld = persistentConcurso.getProvas();
            Set<Prova> provasNew = concurso.getProvas();
            Set<Recurso> attachedRecursosNew = new HashSet<Recurso>();
            for (Recurso recursosNewRecursoToAttach : recursosNew) {
                recursosNewRecursoToAttach = em.getReference(recursosNewRecursoToAttach.getClass(), recursosNewRecursoToAttach.getId());
                attachedRecursosNew.add(recursosNewRecursoToAttach);
            }
            recursosNew = attachedRecursosNew;
            concurso.setRecursos(recursosNew);
            Set<Inscricao> attachedInscricoesNew = new HashSet<Inscricao>();
            for (Inscricao inscricoesNewInscricaoToAttach : inscricoesNew) {
                inscricoesNewInscricaoToAttach = em.getReference(inscricoesNewInscricaoToAttach.getClass(), inscricoesNewInscricaoToAttach.getId());
                attachedInscricoesNew.add(inscricoesNewInscricaoToAttach);
            }
            inscricoesNew = attachedInscricoesNew;
            concurso.setInscricoes(inscricoesNew);
            Set<FatoRelevante> attachedFatosRelevantesNew = new HashSet<FatoRelevante>();
            for (FatoRelevante fatosRelevantesNewFatoRelevanteToAttach : fatosRelevantesNew) {
                fatosRelevantesNewFatoRelevanteToAttach = em.getReference(fatosRelevantesNewFatoRelevanteToAttach.getClass(), fatosRelevantesNewFatoRelevanteToAttach.getId());
                attachedFatosRelevantesNew.add(fatosRelevantesNewFatoRelevanteToAttach);
            }
            fatosRelevantesNew = attachedFatosRelevantesNew;
            concurso.setFatosRelevantes(fatosRelevantesNew);
            Set<Arquivo> attachedArquivosNew = new HashSet<Arquivo>();
            for (Arquivo arquivosNewArquivoToAttach : arquivosNew) {
                arquivosNewArquivoToAttach = em.getReference(arquivosNewArquivoToAttach.getClass(), arquivosNewArquivoToAttach.getId());
                attachedArquivosNew.add(arquivosNewArquivoToAttach);
            }
            arquivosNew = attachedArquivosNew;
            concurso.setArquivos(arquivosNew);
            Set<Prova> attachedProvasNew = new HashSet<Prova>();
            for (Prova provasNewProvaToAttach : provasNew) {
                provasNewProvaToAttach = em.getReference(provasNewProvaToAttach.getClass(), provasNewProvaToAttach.getId());
                attachedProvasNew.add(provasNewProvaToAttach);
            }
            provasNew = attachedProvasNew;
            concurso.setProvas(provasNew);
            concurso = em.merge(concurso);
            for (Recurso recursosOldRecurso : recursosOld) {
                if (!recursosNew.contains(recursosOldRecurso)) {
                    recursosOldRecurso.setConcurso(null);
                    recursosOldRecurso = em.merge(recursosOldRecurso);
                }
            }
            for (Recurso recursosNewRecurso : recursosNew) {
                if (!recursosOld.contains(recursosNewRecurso)) {
                    Concurso oldConcursoOfRecursosNewRecurso = recursosNewRecurso.getConcurso();
                    recursosNewRecurso.setConcurso(concurso);
                    recursosNewRecurso = em.merge(recursosNewRecurso);
                    if (oldConcursoOfRecursosNewRecurso != null && !oldConcursoOfRecursosNewRecurso.equals(concurso)) {
                        oldConcursoOfRecursosNewRecurso.getRecursos().remove(recursosNewRecurso);
                        oldConcursoOfRecursosNewRecurso = em.merge(oldConcursoOfRecursosNewRecurso);
                    }
                }
            }
            for (Inscricao inscricoesOldInscricao : inscricoesOld) {
                if (!inscricoesNew.contains(inscricoesOldInscricao)) {
                    inscricoesOldInscricao.setConcurso(null);
                    inscricoesOldInscricao = em.merge(inscricoesOldInscricao);
                }
            }
            for (Inscricao inscricoesNewInscricao : inscricoesNew) {
                if (!inscricoesOld.contains(inscricoesNewInscricao)) {
                    Concurso oldConcursoOfInscricoesNewInscricao = inscricoesNewInscricao.getConcurso();
                    inscricoesNewInscricao.setConcurso(concurso);
                    inscricoesNewInscricao = em.merge(inscricoesNewInscricao);
                    if (oldConcursoOfInscricoesNewInscricao != null && !oldConcursoOfInscricoesNewInscricao.equals(concurso)) {
                        oldConcursoOfInscricoesNewInscricao.getInscricoes().remove(inscricoesNewInscricao);
                        oldConcursoOfInscricoesNewInscricao = em.merge(oldConcursoOfInscricoesNewInscricao);
                    }
                }
            }
            for (FatoRelevante fatosRelevantesOldFatoRelevante : fatosRelevantesOld) {
                if (!fatosRelevantesNew.contains(fatosRelevantesOldFatoRelevante)) {
                    fatosRelevantesOldFatoRelevante.setConcurso(null);
                    fatosRelevantesOldFatoRelevante = em.merge(fatosRelevantesOldFatoRelevante);
                }
            }
            for (FatoRelevante fatosRelevantesNewFatoRelevante : fatosRelevantesNew) {
                if (!fatosRelevantesOld.contains(fatosRelevantesNewFatoRelevante)) {
                    Concurso oldConcursoOfFatosRelevantesNewFatoRelevante = fatosRelevantesNewFatoRelevante.getConcurso();
                    fatosRelevantesNewFatoRelevante.setConcurso(concurso);
                    fatosRelevantesNewFatoRelevante = em.merge(fatosRelevantesNewFatoRelevante);
                    if (oldConcursoOfFatosRelevantesNewFatoRelevante != null && !oldConcursoOfFatosRelevantesNewFatoRelevante.equals(concurso)) {
                        oldConcursoOfFatosRelevantesNewFatoRelevante.getFatosRelevantes().remove(fatosRelevantesNewFatoRelevante);
                        oldConcursoOfFatosRelevantesNewFatoRelevante = em.merge(oldConcursoOfFatosRelevantesNewFatoRelevante);
                    }
                }
            }
            for (Arquivo arquivosOldArquivo : arquivosOld) {
                if (!arquivosNew.contains(arquivosOldArquivo)) {
                    arquivosOldArquivo.setConcurso(null);
                    arquivosOldArquivo = em.merge(arquivosOldArquivo);
                }
            }
            for (Arquivo arquivosNewArquivo : arquivosNew) {
                if (!arquivosOld.contains(arquivosNewArquivo)) {
                    Concurso oldConcursoOfArquivosNewArquivo = arquivosNewArquivo.getConcurso();
                    arquivosNewArquivo.setConcurso(concurso);
                    arquivosNewArquivo = em.merge(arquivosNewArquivo);
                    if (oldConcursoOfArquivosNewArquivo != null && !oldConcursoOfArquivosNewArquivo.equals(concurso)) {
                        oldConcursoOfArquivosNewArquivo.getArquivos().remove(arquivosNewArquivo);
                        oldConcursoOfArquivosNewArquivo = em.merge(oldConcursoOfArquivosNewArquivo);
                    }
                }
            }
            for (Prova provasOldProva : provasOld) {
                if (!provasNew.contains(provasOldProva)) {
                    provasOldProva.setConcurso(null);
                    provasOldProva = em.merge(provasOldProva);
                }
            }
            for (Prova provasNewProva : provasNew) {
                if (!provasOld.contains(provasNewProva)) {
                    Concurso oldConcursoOfProvasNewProva = provasNewProva.getConcurso();
                    provasNewProva.setConcurso(concurso);
                    provasNewProva = em.merge(provasNewProva);
                    if (oldConcursoOfProvasNewProva != null && !oldConcursoOfProvasNewProva.equals(concurso)) {
                        oldConcursoOfProvasNewProva.getProvas().remove(provasNewProva);
                        oldConcursoOfProvasNewProva = em.merge(oldConcursoOfProvasNewProva);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                long id = concurso.getId();
                if (findConcurso(id) == null) {
                    throw new NonexistentEntityException("The concurso with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(long id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Concurso concurso;
            try {
                concurso = em.getReference(Concurso.class, id);
                concurso.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The concurso with id " + id + " no longer exists.", enfe);
            }
            Set<Recurso> recursos = concurso.getRecursos();
            for (Recurso recursosRecurso : recursos) {
                recursosRecurso.setConcurso(null);
                recursosRecurso = em.merge(recursosRecurso);
            }
            Set<Inscricao> inscricoes = concurso.getInscricoes();
            for (Inscricao inscricoesInscricao : inscricoes) {
                inscricoesInscricao.setConcurso(null);
                inscricoesInscricao = em.merge(inscricoesInscricao);
            }
            Set<FatoRelevante> fatosRelevantes = concurso.getFatosRelevantes();
            for (FatoRelevante fatosRelevantesFatoRelevante : fatosRelevantes) {
                fatosRelevantesFatoRelevante.setConcurso(null);
                fatosRelevantesFatoRelevante = em.merge(fatosRelevantesFatoRelevante);
            }
            Set<Arquivo> arquivos = concurso.getArquivos();
            for (Arquivo arquivosArquivo : arquivos) {
                arquivosArquivo.setConcurso(null);
                arquivosArquivo = em.merge(arquivosArquivo);
            }
            Set<Prova> provas = concurso.getProvas();
            for (Prova provasProva : provas) {
                provasProva.setConcurso(null);
                provasProva = em.merge(provasProva);
            }
            em.remove(concurso);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Concurso> findConcursoEntities() {
        return findConcursoEntities(true, -1, -1);
    }

    public List<Concurso> findConcursoEntities(int maxResults, int firstResult) {
        return findConcursoEntities(false, maxResults, firstResult);
    }

    private List<Concurso> findConcursoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Concurso as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Concurso findConcurso(long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Concurso.class, id);
        } finally {
            em.close();
        }
    }

    public int getConcursoCount() {
        EntityManager em = getEntityManager();
        try {
            return ((Long) em.createQuery("select count(o) from Concurso as o").getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
